package cn.kepu.elearning.dto.match;

import cn.kepu.elearning.common.Constants;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Endy
 * @create 2019-12-12 上午9:12
 **/
@Getter
@Setter
@ToString(callSuper = true)
public class MatchQueryTrainDTO extends CommonQueryDTO {

    private String cad_report;
    private String isEnrolled;
    /**
     * 和 startTime ， endTime 两个字段作比较，格式为 yyyy-MM
     */
    private String seTime;

    private String tenantId;
    private String ifTenantId;
    private String trainTypeID;
    private String itemType;
    private List<String> orgSeqList;
    /**
     * 值为1则查询课程形式，值为2则不查询课程形式
     */
    private Integer searchType;


    public MatchQueryDTO convert() {
        MatchQueryDTO matchQueryDTO = new MatchQueryDTO();
        matchQueryDTO.setType(Constants.Type.TRAIN);
        matchQueryDTO.setPageNum(this.getPageNum());
        matchQueryDTO.setPageSize(this.getPageSize());
        matchQueryDTO.setFilterText(this.getFilterText());
        matchQueryDTO.setFieldNames(this.getFieldNames());
        matchQueryDTO.setOther(generatorOther());
        return matchQueryDTO;
    }

    private List<OtherQueryDTO> generatorOther() {
        List<OtherQueryDTO> other = new ArrayList<>();
        if (StringUtils.isNotBlank(this.getCad_report())) {
            OtherQueryDTO other0 = new OtherQueryDTO();
            other0.setField("cad_report");
            other0.setFieldType("number");
            other0.setValue(this.getCad_report());
            other0.setOperator(Constants.Operator.TERM);
            other0.setLogicOperator(Constants.LogicOperator.MUST);
            other.add(other0);
        }
        if (StringUtils.isNotBlank(this.getIsEnrolled())) {
            String now = Constants.ES_DATE_PATTERN.format(new Date());
            if ("1".equals(this.getIsEnrolled())) {
                // 判断 isEnrolled == 1 并且当前时间在 programStartTime，programEndTime 之间
                OtherQueryDTO other0 = new OtherQueryDTO();
                other0.setLogicOperator(Constants.LogicOperator.MUST);

                List<OtherQueryDTO> subOther = new ArrayList<>();
                OtherQueryDTO subSubOther1 = new OtherQueryDTO();
                subSubOther1.setField("isEnrolled");
                subSubOther1.setFieldType("number");
                subSubOther1.setValue("1");
                subSubOther1.setOperator(Constants.Operator.TERM);
                subSubOther1.setLogicOperator(Constants.LogicOperator.MUST);
                subOther.add(subSubOther1);
                OtherQueryDTO subSubOther2 = new OtherQueryDTO();
                subSubOther2.setField("programStartTime");
                subSubOther2.setFieldType("date");
                subSubOther2.setValue(now);
                subSubOther2.setOperator(Constants.Operator.RANGE_LT);
                subSubOther2.setLogicOperator(Constants.LogicOperator.MUST);
                subOther.add(subSubOther2);
                OtherQueryDTO subSubOther3 = new OtherQueryDTO();
                subSubOther3.setField("programEndTime");
                subSubOther3.setFieldType("date");
                subSubOther3.setValue(now);
                subSubOther3.setOperator(Constants.Operator.RANGE_GT);
                subSubOther3.setLogicOperator(Constants.LogicOperator.MUST);
                subOther.add(subSubOther3);

                other0.setSubOther(subOther);
                other.add(other0);
            } else if ("0".equals(this.getIsEnrolled())) {
                OtherQueryDTO other0 = new OtherQueryDTO();
                other0.setLogicOperator(Constants.LogicOperator.MUST);

                List<OtherQueryDTO> subOther = new ArrayList<>();
                subOther.add(generatorSubOther1(now));
                other0.setSubOther(subOther);

                other.add(other0);
            }
        }

        if (StringUtils.isNotBlank(this.getSeTime())) {
            OtherQueryDTO otherQuery = new OtherQueryDTO();
            otherQuery.setLogicOperator(Constants.LogicOperator.MUST);

            otherQuery.setSubOther(getStartTimeOrEndTime());
            other.add(otherQuery);
        }

        if (StringUtils.isNotBlank(this.getItemType())) {
            OtherQueryDTO other1 = new OtherQueryDTO();
            other1.setField("item_type");
            other1.setFieldType("number");
            other1.setValue(this.getItemType());
            other1.setOperator(Constants.Operator.TERM);
            other1.setLogicOperator(Constants.LogicOperator.MUST);
            other.add(other1);
        } else {
            OtherQueryDTO other1 = new OtherQueryDTO();
            other1.setField("item_type");
            other1.setFieldType("number");
            other1.setValue("0");
            other1.setOperator(Constants.Operator.TERM);
            other1.setLogicOperator(Constants.LogicOperator.MUST_NOT);
            other.add(other1);
        }

        if (StringUtils.isNotBlank(this.getTrainTypeID())) {
            OtherQueryDTO other2 = new OtherQueryDTO();
            other2.setField("trainTypeID");
            other2.setFieldType("number");
            other2.setValue(this.getTrainTypeID());
            other2.setOperator(Constants.Operator.TERM);
            other2.setLogicOperator(Constants.LogicOperator.MUST);
            other.add(other2);
        }

        if (StringUtils.isNotBlank(this.getIfTenantId()) && StringUtils.isNotBlank(this.getTenantId())) {
            if ("2701".equals(this.getIfTenantId())) {
                OtherQueryDTO other3 = new OtherQueryDTO();
                other3.setField("tenantId");
                other3.setFieldType("number");
                other3.setValue(this.getTenantId());
                other3.setOperator(Constants.Operator.TERM);
                other3.setLogicOperator(Constants.LogicOperator.MUST);
                other.add(other3);
            } else if ("2702".equals(this.getIfTenantId())) {
                OtherQueryDTO other3 = new OtherQueryDTO();
                other3.setField("tenantId");
                other3.setFieldType("number");
                other3.setValue(this.getTenantId());
                other3.setOperator(Constants.Operator.TERM);
                other3.setLogicOperator(Constants.LogicOperator.MUST_NOT);
                other.add(other3);
            }
        }
        if (!CollectionUtils.isEmpty(this.getOrgSeqList())) {
            OtherQueryDTO other4;
            for (String s : this.getOrgSeqList()) {
                other4 = new OtherQueryDTO();
                other4.setField("openOrgSEQ");
                other4.setFieldType("string");
                other4.setValue(s);
                other4.setOperator(Constants.Operator.TERM);
                other4.setLogicOperator(Constants.LogicOperator.SHOULD);
                other.add(other4);
            }
        }
        return other;
    }

    private List<OtherQueryDTO> getStartTimeOrEndTime() {
        LocalDate localDateTime = LocalDate.parse(this.getSeTime() + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate firstDayOfMonth = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate firstDayOfNextMonth = localDateTime.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
        // sTime 所在月份的第一天的0点
        Date date = Date.from(firstDayOfMonth.atStartOfDay(ZoneId.systemDefault()).toInstant());
        String firstDay = Constants.ES_DATE_PATTERN.format(date);

        // sTime 下个月的第一天的0点
        Date lastdate = Date.from(firstDayOfNextMonth.atStartOfDay(ZoneId.systemDefault()).toInstant());
        String lastDay = Constants.ES_DATE_PATTERN.format(lastdate);


        List<OtherQueryDTO> subOtherQuery = new ArrayList<>();
        OtherQueryDTO other1 = new OtherQueryDTO();
        other1.setLogicOperator(Constants.LogicOperator.SHOULD);
        List<OtherQueryDTO> subOther = new ArrayList<>();
        OtherQueryDTO subOther1 = new OtherQueryDTO();
        subOther1.setField("startTime");
        subOther1.setFieldType("date");
        subOther1.setValue(firstDay);
        subOther1.setSValue(lastDay);
        subOther1.setOperator(Constants.Operator.BETWEEN);
        subOther1.setLogicOperator(Constants.LogicOperator.MUST);
        subOther.add(subOther1);
        OtherQueryDTO subOther2 = new OtherQueryDTO();
        subOther2.setField("endTime");
        subOther2.setFieldType("date");
        subOther2.setValue(firstDay);
        subOther2.setSValue(lastDay);
        subOther2.setOperator(Constants.Operator.BETWEEN);
        subOther2.setLogicOperator(Constants.LogicOperator.MUST);
        subOther.add(subOther2);
        other1.setSubOther(subOther);
        subOtherQuery.add(other1);
        return subOtherQuery;
    }


    private OtherQueryDTO generatorSubOther1(String now) {
        OtherQueryDTO subOther1 = new OtherQueryDTO();
        subOther1.setLogicOperator(Constants.LogicOperator.SHOULD);
        List<OtherQueryDTO> subSubOther = new ArrayList<>();
        OtherQueryDTO subSubOther1 = new OtherQueryDTO();
        subSubOther1.setField("isEnrolled");
        subSubOther1.setFieldType("number");
        subSubOther1.setValue("0");
        subSubOther1.setOperator(Constants.Operator.TERM);
        subSubOther1.setLogicOperator(Constants.LogicOperator.MUST);
        subSubOther.add(subSubOther1);

        OtherQueryDTO subSubOther2 = new OtherQueryDTO();
        subSubOther2.setLogicOperator(Constants.LogicOperator.MUST);
        List<OtherQueryDTO> subSubSubOther = new ArrayList<>();
        OtherQueryDTO subSubSubOther1 = new OtherQueryDTO();
        subSubSubOther1.setField("isEnrolled");
        subSubSubOther1.setFieldType("number");
        subSubSubOther1.setValue("1");
        subSubSubOther1.setOperator(Constants.Operator.TERM);
        subSubSubOther1.setLogicOperator(Constants.LogicOperator.MUST);
        subSubSubOther.add(subSubSubOther1);

        subSubSubOther.add(getProgramTimeOther(now));
        subSubOther2.setSubOther(subSubSubOther);

        subSubOther.add(subSubOther2);
        subOther1.setSubOther(subSubOther);
        return subOther1;
    }

    private OtherQueryDTO getProgramTimeOther(String now) {
        OtherQueryDTO subTimeOther = new OtherQueryDTO();
        subTimeOther.setLogicOperator(Constants.LogicOperator.SHOULD);

        List<OtherQueryDTO> subTimeOtherList = new ArrayList<>();
        OtherQueryDTO subSubSubOther2 = new OtherQueryDTO();
        subSubSubOther2.setField("programStartTime");
        subSubSubOther2.setFieldType("date");
        subSubSubOther2.setValue(now);
        subSubSubOther2.setOperator(Constants.Operator.RANGE_GTE);
        subSubSubOther2.setLogicOperator(Constants.LogicOperator.MUST);
        subTimeOtherList.add(subSubSubOther2);
        OtherQueryDTO subSubSubOther3 = new OtherQueryDTO();
        subSubSubOther3.setField("programEndTime");
        subSubSubOther3.setFieldType("date");
        subSubSubOther3.setValue(now);
        subSubSubOther3.setOperator(Constants.Operator.RANGE_LTE);
        subSubSubOther3.setLogicOperator(Constants.LogicOperator.MUST);
        subTimeOtherList.add(subSubSubOther3);
        subTimeOther.setSubOther(subTimeOtherList);
        return subTimeOther;
    }
}
